﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DBSourceToolsLib.CodeParser
{
    public class ParseObjectList : ParseObject
    {

        private List<ParseObject> m_ObjectList = new List<ParseObject>();
        public ParseObjectList(int iLineIdx, int iWordIdx)
            : base(ParseObject.LIST, ParseObject.LIST, false, iLineIdx, iWordIdx)
        {
        }

        public void Resolve( List<ParseObject> oList) {

            int iBraceType = -1;
            iBraceType = ParseObjectList.FindBraceType(oList);
            if (iBraceType > -1)
            {
                int iFirstIdx, iLastIdx;
                List<ParseObject> matchedBraces = new List<ParseObject>();

                ParseObjectList.MatchStartAndEndBrace(oList, ref matchedBraces, out iFirstIdx, out iLastIdx, iBraceType);


                if ((iFirstIdx > -1) && (iLastIdx > -1))
                {
                    for (int i = 0; i <= iFirstIdx; i++)
                        m_ObjectList.Add(oList[i]);

                    List<ParseObject> innerList = ParseObjectList.InnerList(matchedBraces, ParseObject.BRACE);
                    if (ParseObjectList.FindBraceType(innerList) > -1)
                    {

                        ParseObjectList oParseObjectListChild = new ParseObjectList(1,1);
                        oParseObjectListChild.Resolve(innerList);
                        m_ObjectList.Add(oParseObjectListChild);
                    }
                    else
                    {
                        if (iBraceType == ParseBrace.DOUBLE_QUOTE || iBraceType == ParseBrace.SINGLE_QUOTE)
                        {
                            ParseLiteral oLiteral = new ParseLiteral(innerList,1,1);
                            m_ObjectList.Add(oLiteral);
                        }
                        else
                        {

                            foreach (ParseObject oNoBraceObject in innerList)
                                m_ObjectList.Add(oNoBraceObject);
                        }
                    }

                    for (int i = iLastIdx; i < oList.Count; i++)
                        m_ObjectList.Add(oList[i]);
                }
                else
                {
                    //m_parseObjectList = listParseData;
                }

            }
            else
            {
                foreach (ParseObject oObject in oList)
                    m_ObjectList.Add(oObject);
                //m_parseObjectList = listParseData;
            }


            //if (oList.Count > 0)
            //{
            //    foreach (ParseObject oObject in oList)
            //        m_ObjectList.Add(oObject);
            //}

        }


        public static void MatchStartAndEndBrace(List<ParseObject> lstParseObjects, ref List<ParseObject>
            oResultList, out int iFirstQuoteIdx, out int iLastQuoteIdx, params int[] arrBraceTypes)
        {
            oResultList = new List<ParseObject>();
            bool bValid = false;
            int iQuoteType = -1;
            iFirstQuoteIdx = iLastQuoteIdx = -1;
            for (int i = 0; i < lstParseObjects.Count; i++)
            {
                if (IsQuote(lstParseObjects[i], arrBraceTypes))
                {
                    iFirstQuoteIdx = i;
                    iQuoteType = lstParseObjects[i].Value;
                    break;
                }
            }
            if (iQuoteType > 0)
            {
                for (int i = lstParseObjects.Count - 1; i > -1; i--)
                {
                    if (IsQuote(lstParseObjects[i], GetOpposingBraceType(iQuoteType)))
                    {
                        iLastQuoteIdx = i;
                        bValid = true;
                        break;
                    }
                }
            }

            for (int i = iFirstQuoteIdx; i <= iLastQuoteIdx; i++)
                oResultList.Add(lstParseObjects[i]);

            
        }

        private static bool IsQuote(ParseObject parseObject, params int[] matchQuoteTypes)
        {
            if (parseObject.ParseType == ParseObject.BRACE)
            {
                if (matchQuoteTypes.Length > 0)
                {
                    for (int i = 0; i < matchQuoteTypes.Length; i++)
                        if (parseObject.Value == matchQuoteTypes[i])
                            return true;
                }
                else
                    return true;
            }
            return false;
        }

        private static int GetOpposingBraceType(int iQuoteType)
        {
            switch (iQuoteType)
            {
                case ParseBrace.BRACE_START:
                    return ParseBrace.BRACE_END;
                case ParseBrace.BRACKET_START:
                    return ParseBrace.BRACKET_END;
                default:
                    return iQuoteType;
            }

        }


        internal static int FindBraceType(List<ParseObject> listParseData)
        {
            foreach (ParseObject oParseObject in listParseData)
            {
                switch (oParseObject.ParseType)
                {
                    case ParseObject.BRACE:
                        return oParseObject.Value;
                }
            }
            return -1;
        }


        internal static List<ParseObject> InnerList(List<ParseObject> listParseData, int p)
        {
            List<ParseObject> oInnerList = new List<ParseObject>();
            for (int i = 1; i < (listParseData.Count - 1); i++)
                oInnerList.Add(listParseData[i]);
            return oInnerList;
        }

        public override string DumpToString()
        {

            StringBuilder oBuilder = new StringBuilder();
            oBuilder.AppendLine("ParseObjectList:");
            foreach (ParseObject oObject in m_ObjectList)
                oBuilder.AppendLine(oObject.DumpToString());
            return oBuilder.ToString();
        }

    }
}
